#!/usr/bin/perl
# Chatlogs -- Highlight xchat (IRC) logs.
# Copyleft (C) 2006 Dullboy, dullgiulio at gmail dot com
# 
# You can freely improve or use/abuse this script.

use strict;

# String to be appended before N.html (N is the page number)
my $output = 'chatlog-';
# Number of lines in each page. 0 or less means all in one file. 
my $linemax = 0;

use vars qw($month $day $hours
	    $min $sec $line
	    $reminder $nick $message);

my @RAND_COLORS = qw(#ffcccc #ccffe6 #ccccff #e6ccff #ffccff #ffcce6 #ff9999 #ffcc99 #ffff99
		     #ccff99 #99ff99 #99ffcc #99ccff #9999ff #cc99ff #ff6666 #ffb366 #ffff66
		     #66ff66 #66ffb3 #66b3ff #6666ff #ff3333 #33ff33 #3399ff #3333ff #ff3399
		     #a0a0a0 #ff0000 #ffff00 #80ff00 #0000ff #8000ff #ff00ff #ff0080 #994d00
		     #999900 #009900 #cc0066 #c0c0c0 #ccff99 #99ff33 #808080 #660033 #ffffff);
my %NICKS_HASH;

sub format_message
{
   my $msg = shift;
  
   # Highlight channels + #color hack.
   $msg =~ s/[^#"](#[A-Za-z0-9_\-]+)/<b><tt>&nbsp;\1<\/tt><\/b>/g;
   $msg =~ s/##/#/g;

   # XXX: The OR at the end means that in a line such as "http://a.com/ a.b.com" only
   #	  the first will be highlighted. Damn!

   $msg =~ s/([a-z]+:\/\/[^\s]+)/<tt><a href="\1">\1<\/a><\/tt>/g ||
   
   # XXX: Please notice that this regex is absolutely insane: it just works most of the times.
   #	  Links without a protocol have a http:// appended, which may not be what was needed.
   $msg =~ s/([A-Za-z0-9_\-\/]+(\.[A-Za-z0-9_\-\/\=~\&\%\?:;]+){2,})/<tt><a href="http:\/\/\1">\1<\/a><\/tt>/g;


   # PIG UTF-8, i.e. how to do it nasty.
   $msg =~ s/\xc3(\x83\xc2)?[\xa8\xa9]/&egrave;/g;
   $msg =~ s/\xc3(\x83\xc2)?\xa0/&agrave;/g;
   $msg =~ s/\xc3(\x83\xc2)?\xb9/&ugrave;/g;
   $msg =~ s/\xc3(\x83\xc2)?\xac/&igrave;/g;
   $msg =~ s/\xc3(\x83\xc2)?\xb2/&ograve;/g;
   $msg =~ s/\xc3(\x83\xc2)?\x88/E`/g;

   return $msg;
}

sub print_begin {
   print OUTPUT "<html><body bgcolor=\"#000000\" style=\"color: #ffffff; font-size: 10px\">\n";
}

sub print_end {
   print OUTPUT "</body></html>";
}

# Current line number.
my $linecount = 0;
# Number of page generated.
my $chats = 1;

open(INPUT, "<$ARGV[0]") || die "Can't open input file $ARGV[0]";
open(OUTPUT, ">$output$chats.html") || die "Can't open output file";
print_begin();

while (<INPUT>) {
   $line = $_;
   chomp $line;

   $linecount ++;

   if ($linecount > $linemax && $linemax > 0) {
      if ($chats >= 2) {
        printf(OUTPUT "<hr><a href=\"$output%d.html\">Previous</a>\n", $chats-1);
      } else {
        printf(OUTPUT "<hr>Previous\n");
      }
      printf(OUTPUT "<a href=\"$output%d.html\">Next</a> -- <tt>Generated by <b>chatlogs</b></tt>\n", $chats+1);
      print_end();
      close(OUTPUT);
      
      $chats++;
      open(OUTPUT, ">$output$chats.html") || die "Can't open output file";
      print_begin();
      $linecount = 0;
   }

   if ($line =~ /^[A-Za-z]{3} / || $line=~ /^\s*</) {
      ($month, $day, $hours, $min, $sec, $reminder) =
      		($line =~ /^([A-Za-z]{3})? ?([0-9]{2})? ?([0-9]{2})?:?([0-9]{2})?:?([0-9]{2})?(\s*.+)/);
      ($nick, $message) = ($reminder =~ /\s*<([A-Za-z0-9_`\^\|\(\)\[\]\{\}]+)?>\s+(.*)/);
      
      unless ($message) {
         $message = $reminder;
      }
      
      #$message =~ s/^\s+/\s/;
      $message =~ s/&/&amp;/g;
      $message =~ s/</&lt;/g;
      $message =~ s/>/&gt;/g;
      $reminder =~ s/^\s+/\s/;

      if ($hours) {
         print OUTPUT "<font color=\"#a0a0a0\"><tt>$hours:$min:$sec</tt></font> ";
      }

      if ($nick) {
         # A nickname bethween < and > could be new (entered the chan before of us),
	 # we add it to the colors list.
         unless (defined($NICKS_HASH{$nick})) {
	    $NICKS_HASH{$nick} = int(rand($#RAND_COLORS));
	 }
	 # Write the name...
         print OUTPUT " &lt;<font color=\"".$RAND_COLORS[$NICKS_HASH{$nick}]."\">$nick</font>&gt;&nbsp;\n";
      }
      elsif ($reminder =~ /\s*-->\s+/) {
         # User has entered the chat. If unknown we add the new nick to the
	 # colors list. It will be highlighted later on.
         ($nick, $_) = ($reminder =~ /([A-Za-z0-9_`\^\|\*\{\}\[\]\(\)]+)(\s+\()/);
	 if ($nick) {
	    if ($NICKS_HASH{$nick} eq "") {
	       $NICKS_HASH{$nick} = int(rand($#RAND_COLORS));
	    }
	 }
      }
      #elsif ($reminder =~ /\s*<--\t+/) {
         # User has left the chat: We don't to anything, such as
	 # deleting the user from the colors. He/She might come back.
      #}
      else {
	 # A nick changes his/her name, keep the same color.
	 if ($message =~ /is now known as/) {
	    my ($old, $new) = ($message =~ /([A-Za-z0-9_`\^\|\(\)\[\]\{\}]+) is now known as ([A-Za-z0-9_`\^\|\(\)\[\]\{\}]+)/);
	    my $oldcolor = $NICKS_HASH{$old};
	    delete $NICKS_HASH{$old};
	    $NICKS_HASH{$new} = $oldcolor;
	 } elsif ($message =~ /Topic for #[A-Za-z0-9_\-]+ is/) {
	    $message =~ s/is (.*)/is <font color="##ffff00">\1<\/font>/;
	 } elsif ($message =~ /has changed the topic to: /) {
	    $message =~ s/to: (.*)/to: <font color="##ffff00">\1<\/font>/;
	 } elsif ($message =~ /Disconnected/) {
	    $message =~ s/Disconnected/<font color="##cc0000">Disconnected<\/font>/;
	 } elsif ($message =~ /\-(Global|ChanServ)\-/) {
	    $message =~ s/\-(Global|ChanServ)\-/<font color="##0066cc">\-\1\-<\/font>/;
	 } elsif ($message =~ /\-\-\-.+sets mode/) {
	    $message =~ s/(sets mode) (\+[a-z])/<font color="##0066cc">\1<\/font>&nbsp;<font color="##cc0000">\2<\/font>/;
	 }
      }

      if (substr($message, 0, 1) ne ' ') {
         $message = " $message";
      }

      for my $token (split(/\s+([A-Za-z0-9\^\-_`\|\(\)\{\}\[\]]+[\.\,"'\:\?!]*)/, $message)) {
         $token =~ s/[\.\,"'\:\?!]*$//;
	 if (defined ($NICKS_HASH{$token})) {
	    my $color = $RAND_COLORS[$NICKS_HASH{$token}];
	    $message =~ s/$token/<font color="$color">$token<\/font>/g;
	 }
      }

      $message = format_message($message);

      print OUTPUT "$message<br>\n";
   }
   else {
      print OUTPUT "<font color=\"#a0a0a0\">$line</font><br>\n";
   }
}

if ($chats >= 2) {
   printf(OUTPUT "<hr><a href=\"$output%d.html\">Previous</a>\n", $chats-1);
   printf(OUTPUT "Next -- ");
} else {
   printf(OUTPUT "<hr><br>");
}
printf(OUTPUT "<tt>Generated by <b>chatlogs</b></tt>");
print_end();
